OPC Studio User's Guide and Reference
Examples - OPC Unified Architecture - Create a node ID

Following examples are intended to show you many of the options that exist for constructing the node IDs.

.NET

// This example shows different ways of constructing OPC UA node IDs.
//
// Find all latest examples here: https://opclabs.doc-that.com/files/onlinedocs/OPCLabs-OpcStudio/Latest/examples.html .

using System;
using OpcLabs.BaseLib;
using OpcLabs.EasyOpc.UA;
using OpcLabs.EasyOpc.UA.AddressSpace;
using OpcLabs.EasyOpc.UA.AddressSpace.Parsing;
using OpcLabs.EasyOpc.UA.AddressSpace.Parsing.Extensions;
using OpcLabs.EasyOpc.UA.AddressSpace.Standard;
using OpcLabs.EasyOpc.UA.OperationModel;

namespace UADocExamples._UANodeId
{
    class _Construction
    {
        // A node ID specifies a namespace (either by an URI or by an index), and an identifier.
        // The identifier can be numeric (an integer), string, GUID, or opaque.
        public static void Main1()
        {

            // A node ID can be specified in string form (so-called expanded text). 
            // The code below specifies a namespace URI (nsu=...), and an integer identifier (i=...).
            UANodeId nodeId1 = new UANodeId("nsu=http://test.org/UA/Data/ ;i=10853");
            Console.WriteLine(nodeId1);


            // Similarly, with a string identifier (s=...).
            UANodeId nodeId2 = new UANodeId("nsu=http://test.org/UA/Data/ ;s=someIdentifier");
            Console.WriteLine(nodeId2);


            // Actually, "s=" can be omitted (not recommended, though).
            UANodeId nodeId3 = new UANodeId("nsu=http://test.org/UA/Data/ ;someIdentifier");
            Console.WriteLine(nodeId3);
            // Notice that the output is normalized - the "s=" is added again.


            // Similarly, with a GUID identifier (g=...).
            UANodeId nodeId4 = new UANodeId("nsu=http://test.org/UA/Data/ ;g=BAEAF004-1E43-4A06-9EF0-E52010D5CD10");
            Console.WriteLine(nodeId4);
            // Notice that the output is normalized - uppercase letters in the GUI are converted to lowercase, etc.


            // Similarly, with an opaque identifier (b=..., in Base64 encoding).
            UANodeId nodeId5 = new UANodeId("nsu=http://test.org/UA/Data/ ;b=AP8=");
            Console.WriteLine(nodeId5);


            // Namespace index can be used instead of namespace URI. The server is allowed to change the namespace 
            // indices between sessions (except for namespace 0), and for this reason, you should avoid the use of
            // namespace indices, and rather use the namespace URIs whenever possible.
            UANodeId nodeId6 = new UANodeId("ns=2;i=10853");
            Console.WriteLine(nodeId6);


            // Namespace index can be also specified together with namespace URI. This is still safe, but may be 
            // a bit quicker to perform, because the client can just verify the namespace URI instead of looking 
            // it up.
            UANodeId nodeId7 = new UANodeId("nsu=http://test.org/UA/Data/ ;ns=2;i=10853");
            Console.WriteLine(nodeId7);


            // When neither namespace URI nor namespace index are given, the node ID is assumed to be in namespace
            // with index 0 and URI "http://opcfoundation.org/UA/", which is reserved by OPC UA standard. There are 
            // many standard nodes that live in this reserved namespace, but no nodes specific to your servers will 
            // be in the reserved namespace, and hence the need to specify the namespace with server-specific nodes.
            UANodeId nodeId8 = new UANodeId("i=2254");
            Console.WriteLine(nodeId8);


            // If you attempt to pass in a string that does not conform to the syntax rules, 
            // a UANodeIdFormatException is thrown.
            try
            {
                UANodeId nodeId9 = new UANodeId("nsu=http://test.org/UA/Data/ ;i=notAnInteger");
                Console.WriteLine(nodeId9);
            }
            catch (UANodeIdFormatException nodeIdFormatException)
            {
                Console.WriteLine($"*** Failure {nodeIdFormatException.Message}");
            }


            // There is a parser object that can be used to parse the expanded texts of node IDs. 
            UANodeIdParser nodeIdParser10 = new UANodeIdParser();
            UANodeId nodeId10 = nodeIdParser10.Parse("nsu=http://test.org/UA/Data/ ;i=10853");
            Console.WriteLine(nodeId10);


            // The parser can be used if you want to parse the expanded text of the node ID but do not want 
            // exceptions be thrown.
            UANodeIdParser nodeIdParser11 = new UANodeIdParser();
            IStringParsingError stringParsingError =
                nodeIdParser11.TryParse("nsu=http://test.org/UA/Data/ ;i=notAnInteger", out UANodeId nodeId11);
            if (stringParsingError is null)
                Console.WriteLine(nodeId11);
            else
                Console.WriteLine($"*** Failure: {stringParsingError.Message}");


            // You can also use the parser if you have node IDs where you want the default namespace be different 
            // from the standard "http://opcfoundation.org/UA/".
            UANodeIdParser nodeIdParser12 = new UANodeIdParser("http://test.org/UA/Data/");
            UANodeId nodeId12 = nodeIdParser12.Parse("i=10853");
            Console.WriteLine(nodeId12);


            // The namespace URI string (or the namespace index, or both) and the identifier can be passed to the
            // constructor separately.
            UANodeId nodeId13 = new UANodeId("http://test.org/UA/Data/", 10853);
            Console.WriteLine(nodeId13);


            // You can create a "null" node ID. Such node ID does not actually identify any valid node in OPC UA, but 
            // is useful as a placeholder or as a starting point for further modifications of its properties.
            UANodeId nodeId14 = new UANodeId();
            Console.WriteLine(nodeId14);


            // Properties of a node ID can be modified individually. The advantage of this approach is that you do 
            // not have to care about syntax of the node ID expanded text.
            UANodeId nodeId15 = new UANodeId();
            nodeId15.NamespaceUriString = "http://test.org/UA/Data/";
            nodeId15.Identifier = 10853;
            Console.WriteLine(nodeId15);


            // The same as above, but using an object initializer list.
            UANodeId nodeId16 = new UANodeId
            {
                NamespaceUriString = "http://test.org/UA/Data/",
                Identifier = 10853
            };
            Console.WriteLine(nodeId16);


            // If you know the type of the identifier upfront, it is safer to use typed properties that correspond 
            // to specific types of identifier. Here, with an integer identifier.
            UANodeId nodeId17 = new UANodeId();
            nodeId17.NamespaceUriString = "http://test.org/UA/Data/";
            nodeId17.NumericIdentifier = 10853;
            Console.WriteLine(nodeId17);


            // Similarly, with a string identifier.
            UANodeId nodeId18 = new UANodeId();
            nodeId18.NamespaceUriString = "http://test.org/UA/Data/";
            nodeId18.StringIdentifier = "someIdentifier";
            Console.WriteLine(nodeId18);


            // Similarly, with a GUID identifier.
            UANodeId nodeId19 = new UANodeId();
            nodeId19.NamespaceUriString = "http://test.org/UA/Data/";
            nodeId19.GuidIdentifier = Guid.Parse("BAEAF004-1E43-4A06-9EF0-E52010D5CD10");
            Console.WriteLine(nodeId19);


            // If you have GUID in its string form, the node ID object can parse it for you.
            UANodeId nodeId20 = new UANodeId();
            nodeId20.NamespaceUriString = "http://test.org/UA/Data/";
            nodeId20.GuidIdentifierString = "BAEAF004-1E43-4A06-9EF0-E52010D5CD10";
            Console.WriteLine(nodeId20);


            // And, with an opaque identifier.
            UANodeId nodeId21 = new UANodeId();
            nodeId21.NamespaceUriString = "http://test.org/UA/Data/";
            nodeId21.OpaqueIdentifier = new byte[] {0x00, 0xFF};
            Console.WriteLine(nodeId21);


            // Assigning an expanded text to a node ID parses the value being assigned and sets all corresponding
            // properties accordingly.
            UANodeId nodeId22 = new UANodeId();
            nodeId22.ExpandedText = "nsu=http://test.org/UA/Data/ ;i=10853";
            Console.WriteLine(nodeId22);


            // There is an implicit conversion from a string (representing the expanded text) to a node ID.
            // You can therefore use the expanded text (string) in place of any node ID object directly.
            UANodeId nodeId23 = "nsu=http://test.org/UA/Data/ ;i=10853";
            Console.WriteLine(nodeId23);


            // There is a copy constructor as well, creating a clone of an existing node ID.
            UANodeId nodeId24a = new UANodeId("nsu=http://test.org/UA/Data/ ;i=10853");
            Console.WriteLine(nodeId24a);
            UANodeId nodeId24b = new UANodeId(nodeId24a);
            Console.WriteLine(nodeId24b);


            // We have provided static classes with properties that correspond to all standard nodes specified by 
            // OPC UA. You can simply refer to these node IDs in your code.
            // The class names are UADataTypeIds, UAMethodIds, UAObjectIds, UAObjectTypeIds, UAReferenceTypeIds, 
            // UAVariableIds and UAVariableTypeIds.
            UANodeId nodeId25 = UAObjectIds.TypesFolder;
            Console.WriteLine(nodeId25);
            // When the UANodeId equals to one of the standard nodes, it is output in the shortened form - as the standard
            // name only.


            // You can also refer to any standard node using its name (in a string form).
            // Note that assigning a non-existing standard name is not allowed, and throws ArgumentException.
            UANodeId nodeId26 = new UANodeId();
            nodeId26.StandardName = "TypesFolder";
            Console.WriteLine(nodeId26);


            // When you browse for nodes in the OPC UA server, every returned node element contains a node ID that
            // you can use further.
            var client27 = new EasyUAClient();
            try
            {
                UANodeElementCollection nodeElementCollection27 = client27.Browse(
                        "opc.tcp://opcua.demo-this.com:51210/UA/SampleServer",
                        UAObjectIds.Server,
                        new UABrowseParameters(UANodeClass.All, new[] { UAReferenceTypeIds.References }));
                if (nodeElementCollection27.Count != 0)
                {
                    UANodeId nodeId27 = nodeElementCollection27[0].NodeId;
                    Console.WriteLine(nodeId27);
                }
            }
            catch (UAException uaException)
            {
                Console.WriteLine("Failure: {0}", uaException.GetBaseException().Message);
            }


            // As above, but using a constructor that takes a node element as an input.
            var client28 = new EasyUAClient();
            try
            {
                UANodeElementCollection nodeElementCollection28 = client28.Browse(
                    "opc.tcp://opcua.demo-this.com:51210/UA/SampleServer",
                    UAObjectIds.Server,
                    new UABrowseParameters(UANodeClass.All, new[] { UAReferenceTypeIds.References }));
                if (nodeElementCollection28.Count != 0)
                {
                    UANodeId nodeId28 = new UANodeId(nodeElementCollection28[0]);
                    Console.WriteLine(nodeId28);
                }
            }
            catch (UAException uaException)
            {
                Console.WriteLine("Failure: {0}", uaException.GetBaseException().Message);
            }


            // Or, there is an explicit conversion from a node descriptor as well.
            var client29 = new EasyUAClient();
            try
            {
                UANodeElementCollection nodeElementCollection29 = client29.Browse(
                    "opc.tcp://opcua.demo-this.com:51210/UA/SampleServer",
                    UAObjectIds.Server,
                    new UABrowseParameters(UANodeClass.All, new[] { UAReferenceTypeIds.References }));
                if (nodeElementCollection29.Count != 0)
                {
                    UANodeId nodeId29 = (UANodeId) nodeElementCollection29[0];
                    Console.WriteLine(nodeId29);
                }
            }
            catch (UAException uaException)
            {
                Console.WriteLine("Failure: {0}", uaException.GetBaseException().Message);
            }
        }
    }
}
# This example shows different ways of constructing OPC UA node IDs.
#
# Find all latest examples here: https://opclabs.doc-that.com/files/onlinedocs/OPCLabs-OpcStudio/Latest/examples.html .
# OPC client and subscriber examples in Python on GitHub: https://github.com/OPCLabs/Examples-QuickOPC-Python .
# The QuickOPC package is needed. Install it using "pip install opclabs_quickopc".
import opclabs_quickopc

# Import .NET namespaces.
from System import *
from OpcLabs.EasyOpc.UA import *
from OpcLabs.EasyOpc.UA.AddressSpace import *
from OpcLabs.EasyOpc.UA.AddressSpace.Parsing import *
from OpcLabs.EasyOpc.UA.AddressSpace.Parsing.Extensions import *
from OpcLabs.EasyOpc.UA.AddressSpace.Standard import *


# A node ID specifies a namespace (either by an URI or by an index), and an identifier.
# The identifier can be numeric (an integer), string, GUID, or opaque.
#


# A node ID can be specified in string form (so-called expanded text).
# The code below specifies a namespace URI (nsu=...), and an integer identifier (i=...).
nodeId1 = UANodeId('nsu=http://test.org/UA/Data/ ;i=10853')
print(nodeId1)


# Similarly, with a string identifier (s=...).
nodeId2 = UANodeId('nsu=http://test.org/UA/Data/ ;s=someIdentifier')
print(nodeId2)


# Actually, "s=" can be omitted (not recommended, though).
nodeId3 = UANodeId('nsu=http://test.org/UA/Data/ ;someIdentifier')
print(nodeId3)


# Similarly, with a GUID identifier (g=...).
nodeId4 = UANodeId('nsu=http://test.org/UA/Data/ ;g=BAEAF004-1E43-4A06-9EF0-E52010D5CD10')
print(nodeId4)


# Similarly, with an opaque identifier (b=..., in Base64 encoding).
nodeId5 = UANodeId('nsu=http://test.org/UA/Data/ ;b=AP8=')
print(nodeId5)


# Namespace index can be used instead of namespace URI. The server is allowed to change the namespace
# indices between sessions (except for namespace 0), and for this reason, you should avoid the use of
# namespace indices, and rather use the namespace URIs whenever possible.
nodeId6 = UANodeId('ns=2;i=10853')
print(nodeId6)


# Namespace index can be also specified together with namespace URI. This is still safe, but may be
# a bit quicker to perform, because the client can just verify the namespace URI instead of looking
# it up.
nodeId7 = UANodeId('nsu=http://test.org/UA/Data/ ;ns=2;i=10853')
print(nodeId7)


# When neither namespace URI nor namespace index are given, the node ID is assumed to be in namespace
# with index 0 and URI "http://opcfoundation.org/UA/", which is reserved by OPC UA standard. There are
# many standard nodes that live in this reserved namespace, but no nodes specific to your servers will
# be in the reserved namespace, and hence the need to specify the namespace with server-specific nodes.
nodeId8 = UANodeId('i=2254')
print(nodeId8)


# If you attempt to pass in a string that does not conform to the syntax rules,
# a UANodeIdFormatException is thrown.
try:
    nodeId9 = UANodeId('nsu=http://test.org/UA/Data/ ;i=notAnInteger')
except UANodeIdFormatException as nodeIdFormatException:
    print('*** Failure: ', nodeIdFormatException.Message, sep='')


# There is a parser object that can be used to parse the expanded texts of node IDs.
nodeIdParser10 = UANodeIdParser()
nodeId10 = IUANodeIdParserExtension.Parse(nodeIdParser10, 'nsu=http://test.org/UA/Data/ ;i=10853')
print(nodeId10)


# The parser can be used if you want to parse the expanded text of the node ID but do not want
# exceptions be thrown.
nodeIdParser11 = UANodeIdParser()
stringParsingError, nodeId11 = IUANodeIdParserExtension.TryParse(nodeIdParser11,
                                                                 'nsu=http://test.org/UA/Data/ ;i=notAnInteger',
                                                                 UANodeId())    # placeholder for 'out'
if stringParsingError is None:
    print(nodeId11)
else:
    print('*** Failure: ', stringParsingError.Message, sep='')


# You can also use the parser if you have node IDs where you want the default namespace be different
# from the standard "http://opcfoundation.org/UA/".
nodeIdParser12 = UANodeIdParser('http://test.org/UA/Data/')
nodeId12 = IUANodeIdParserExtension.Parse(nodeIdParser12, 'i=10853')
print(nodeId12)


# The namespace URI string (or the namespace index, or both) and the identifier can be passed to the
# constructor separately.
nodeId13 = UANodeId('http://test.org/UA/Data/', 10853)
print(nodeId13)


# You can create a "null" node ID. Such node ID does not actually identify any valid node in OPC UA, but
# is useful as a placeholder or as a starting point for further modifications of its properties.
nodeId14 = UANodeId()
print(nodeId14)


# Properties of a node ID can be modified individually. The advantage of this approach is that you do
# not have to care about syntax of the node ID expanded text.
nodeId15 = UANodeId()
nodeId15.NamespaceUriString = 'http://test.org/UA/Data/'
nodeId15.Identifier = 10853
print(nodeId15)


# If you know the type of the identifier upfront, it is safer to use typed properties that correspond
# to specific types of identifier. Here, with an integer identifier.
nodeId17 = UANodeId()
nodeId17.NamespaceUriString = 'http://test.org/UA/Data/'
nodeId17.NumericIdentifier = 10853
print(nodeId17)


# Similarly, with a string identifier.
nodeId18 = UANodeId()
nodeId18.NamespaceUriString = 'http://test.org/UA/Data/'
nodeId18.StringIdentifier = 'someIdentifier'
print(nodeId18)


# Similarly, with a GUID identifier.
nodeId19 = UANodeId()
nodeId19.NamespaceUriString = 'http://test.org/UA/Data/'
nodeId19.GuidIdentifier = Guid.Parse('BAEAF004-1E43-4A06-9EF0-E52010D5CD10')
print(nodeId19)


# If you have GUID in its string form, the node ID object can parse it for you.
nodeId20 = UANodeId()
nodeId20.NamespaceUriString = 'http://test.org/UA/Data/'
nodeId20.GuidIdentifierString = 'BAEAF004-1E43-4A06-9EF0-E52010D5CD10'
print(nodeId20)


# And, with an opaque identifier.
nodeId21 = UANodeId()
nodeId21.NamespaceUriString = 'http://test.org/UA/Data/'
nodeId21.OpaqueIdentifier = [0x00, 0xFF]
print(nodeId21)


# Assigning an expanded text to a node ID parses the value being assigned and sets all corresponding
# properties accordingly.
nodeId22 = UANodeId()
nodeId22.ExpandedText = 'nsu=http://test.org/UA/Data/ ;i=10853'
print(nodeId22)


# There is a copy constructor as well, creating a clone of an existing node ID.
nodeId24a = UANodeId('nsu=http://test.org/UA/Data/ ;i=10853')
print(nodeId24a)
nodeId24b = UANodeId(nodeId24a)
print(nodeId24b)


# We have provided static classes with properties that correspond to all standard nodes specified by
# OPC UA. You can simply refer to these node IDs in your code.
# The class names are UADataTypeIds, UAMethodIds, UAObjectIds, UAObjectTypeIds, UAReferenceTypeIds,
# UAVariableIds and UAVariableTypeIds.
nodeId25 = UAObjectIds.TypesFolder
print(nodeId25)
# When the UANodeId equals to one of the standard nodes, it is output in the shortened form - as the standard
# name only.


# You can also refer to any standard node using its name (in a string form).
# Note that assigning a non-existing standard name is not allowed, and throws ArgumentException.
nodeId26 = UANodeId()
nodeId26.StandardName = "TypesFolder"
print(nodeId26)


# When you browse for nodes in the OPC UA server, every returned node element contains a node ID that
# you can use further.
client27 = EasyUAClient()
try:
    nodeElementCollection27 = IEasyUAClientExtension.Browse(client27,
        UAEndpointDescriptor('opc.tcp://opcua.demo-this.com:51210/UA/SampleServer'),
        UANodeDescriptor(UAObjectIds.Server),
        UABrowseParameters(UANodeClass.All, UAReferenceTypeIds.References))
    if nodeElementCollection27.Count != 0:
        nodeId27 = nodeElementCollection27.get_Item(0).NodeId
        print(nodeId27)
except UAException as uaException:
    print('*** Failure: ', uaException.GetBaseException().Message, sep='')


# As above, but using a constructor that takes a node element as an input.
client28 = EasyUAClient()
try:
    nodeElementCollection28 = IEasyUAClientExtension.Browse(client28,
        UAEndpointDescriptor('opc.tcp://opcua.demo-this.com:51210/UA/SampleServer'),
        UANodeDescriptor(UAObjectIds.Server),
        UABrowseParameters(UANodeClass.All, UAReferenceTypeIds.References))
    if nodeElementCollection28.Count != 0:
        nodeId28 = UANodeId(nodeElementCollection28.get_Item(0))
        print(nodeId28)
except UAException as uaException:
    print('*** Failure: ', uaException.GetBaseException().Message, sep='')


# Or, there is an explicit conversion from a node descriptor as well.
client29 = EasyUAClient()
try:
    nodeElementCollection29 = IEasyUAClientExtension.Browse(client29,
        UAEndpointDescriptor('opc.tcp://opcua.demo-this.com:51210/UA/SampleServer'),
        UANodeDescriptor(UAObjectIds.Server),
        UABrowseParameters(UANodeClass.All, UAReferenceTypeIds.References))
    if nodeElementCollection29.Count != 0:
        # FromUANodeDescriptor can be used instead of op_Explicit, too.
        nodeId29 = UANodeId.op_Explicit(UANodeDescriptor(nodeElementCollection29.get_Item(0)))
        print(nodeId29)
except UAException as uaException:
    print('*** Failure: ', uaException.GetBaseException().Message, sep='')


print()
print('Finished.')
' This example shows different ways of constructing OPC UA node IDs.
'
' Find all latest examples here: https://opclabs.doc-that.com/files/onlinedocs/OPCLabs-OpcStudio/Latest/examples.html .

Imports System
Imports OpcLabs.BaseLib
Imports OpcLabs.EasyOpc.UA
Imports OpcLabs.EasyOpc.UA.AddressSpace
Imports OpcLabs.EasyOpc.UA.AddressSpace.Parsing
Imports OpcLabs.EasyOpc.UA.AddressSpace.Parsing.Extensions
Imports OpcLabs.EasyOpc.UA.AddressSpace.Standard

Namespace _UANodeId
    Friend Class _Construction
        Public Shared Sub Main1()

            ' A node ID can be specified in string form (so-called expanded text). 
            ' The code below specifies a namespace URI (nsu=...), and an integer identifier (i=...).
            Dim nodeId1 = New UANodeId("nsu=http://test.org/UA/Data/ ;i=10853")
            Console.WriteLine(nodeId1)


            ' Similarly, with a string identifier (s=...).
            Dim nodeId2 = New UANodeId("nsu=http://test.org/UA/Data/ ;s=someIdentifier")
            Console.WriteLine(nodeId2)


            ' Actually, "s=" can be omitted (not recommended, though)
            Dim nodeId3 = New UANodeId("nsu=http://test.org/UA/Data/ ;someIdentifier")
            Console.WriteLine(nodeId3)


            ' Similarly, with a GUID identifier (g=...)
            Dim nodeId4 = New UANodeId("nsu=http://test.org/UA/Data/ ;g=BAEAF004-1E43-4A06-9EF0-E52010D5CD10")
            Console.WriteLine(nodeId4)


            ' Similarly, with an opaque identifier (b=..., in Base64 encoding).
            Dim nodeId5 = New UANodeId("nsu=http://test.org/UA/Data/ ;b=AP8=")
            Console.WriteLine(nodeId5)


            ' Namespace index can be used instead of namespace URI. The server is allowed to change the namespace 
            ' indices between sessions, and for this reason, you should avoid the use of namespace indices, and
            ' rather use the namespace URIs whenever possible.
            Dim nodeId6 = New UANodeId("ns=2;i=10853")
            Console.WriteLine(nodeId6)


            ' Namespace index can be also specified together with namespace URI. This is still safe, but may be 
            ' a bit quicker to perform, because the client can just verify the namespace URI instead of looking 
            ' it up.
            Dim nodeId7 = New UANodeId("nsu=http://test.org/UA/Data/ ;ns=2;i=10853")
            Console.WriteLine(nodeId7)


            ' When neither namespace URI nor namespace index are given, the node ID is assumed to be in namespace
            ' with index 0 and URI "http://opcfoundation.org/UA/", which is reserved by OPC UA standard. There are 
            ' many standard nodes that live in this reserved namespace, but no nodes specific to your servers will 
            ' be in the reserved namespace, and hence the need to specify the namespace with server-specific nodes.
            Dim nodeId8 = New UANodeId("i=2254")
            Console.WriteLine(nodeId8)


            ' If you attempt to pass in a string that does not conform to the syntax rules, 
            ' a UANodeIdFormatException is thrown.
            Try
                Dim nodeId9 = New UANodeId("nsu=http://test.org/UA/Data/ ;i=notAnInteger")
                Console.WriteLine(nodeId9)
            Catch nodeIdFormatException As UANodeIdFormatException
                Console.WriteLine(nodeIdFormatException.Message)
            End Try


            ' There is a parser object that can be used to parse the expanded textx of node IDs. 
            Dim nodeIdParser10 = New UANodeIdParser()
            Dim nodeId10 = nodeIdParser10.Parse("nsu=http://test.org/UA/Data/ ;i=10853")
            Console.WriteLine(nodeId10)


            ' The parser can be used if you want to parse the expanded text of the node ID but do not want 
            ' exceptions be thrown.
            Dim nodeIdParser11 = New UANodeIdParser()
            Dim nodeId11 As UANodeId = Nothing
            Dim stringParsingError As IStringParsingError =
                    nodeIdParser11.TryParse("nsu=http://test.org/UA/Data/ ;i=notAnInteger", nodeId11)
            If stringParsingError Is Nothing Then
                Console.WriteLine(nodeId11)
            Else
                Console.WriteLine(stringParsingError.Message)
            End If


            ' You can also use the parser if you have node IDs where you want the default namespace be different 
            ' from the standard "http://opcfoundation.org/UA/".
            Dim nodeIdParser12 = New UANodeIdParser("http://test.org/UA/Data/")
            Dim nodeId12 = nodeIdParser12.Parse("i=10853")
            Console.WriteLine(nodeId12)


            ' The namespace URI string (or the namespace index, or both) and the identifier can be passed to the
            ' constructor separately.
            Dim nodeId13 = New UANodeId("http://test.org/UA/Data/", 10853)
            Console.WriteLine(nodeId13)


            ' You can create a "null" node ID. Such node ID does not actually identify any valid node in OPC UA, but 
            ' is useful as a placeholder or as a starting point for further modifications of its properties.
            Dim nodeId14 = New UANodeId()
            Console.WriteLine(nodeId14)


            ' Properties of a node ID can be modified individually. The advantage of this approach is that you do 
            ' not have to care about syntax of the node ID expanded text.
            Dim nodeId15 = New UANodeId()
            nodeId15.NamespaceUriString = "http://test.org/UA/Data/"
            nodeId15.Identifier = 10853
            Console.WriteLine(nodeId15)


            ' The same as above, but using an object initializer list.
            Dim nodeId16 = New UANodeId With
            {
                .NamespaceUriString = "http://test.org/UA/Data/",
                .Identifier = 10853
            }
            Console.WriteLine(nodeId16)


            ' If you know the type of the identifier upfront, it is safer to use typed properties that correspond 
            ' to specific types of identifier. Here, with an integer identifier.
            Dim nodeId17 = New UANodeId()
            nodeId17.NamespaceUriString = "http://test.org/UA/Data/"
            nodeId17.NumericIdentifier = 10853
            Console.WriteLine(nodeId17)


            ' Similarly, with a string identifier.
            Dim nodeId18 = New UANodeId()
            nodeId18.NamespaceUriString = "http://test.org/UA/Data/"
            nodeId18.StringIdentifier = "someIdentifier"
            Console.WriteLine(nodeId18)


            ' Similarly, with a GUID identifier.
            Dim nodeId19 = New UANodeId()
            nodeId19.NamespaceUriString = "http://test.org/UA/Data/"
            nodeId19.GuidIdentifier = Guid.Parse("BAEAF004-1E43-4A06-9EF0-E52010D5CD10")
            Console.WriteLine(nodeId19)


            ' If you have GUID in its string form, the node ID object can parse it for you.
            Dim nodeId20 = New UANodeId()
            nodeId20.NamespaceUriString = "http://test.org/UA/Data/"
            nodeId20.GuidIdentifierString = "BAEAF004-1E43-4A06-9EF0-E52010D5CD10"
            Console.WriteLine(nodeId20)


            ' And, with an opaque identifier.
            Dim nodeId21 = New UANodeId()
            nodeId21.NamespaceUriString = "http://test.org/UA/Data/"
            nodeId21.OpaqueIdentifier = {&H0, &HFF}
            Console.WriteLine(nodeId21)


            ' Assigning an expanded text to a node ID parses the value being assigned and sets all corresponding
            ' properties accordingly.
            Dim nodeId22 = New UANodeId()
            nodeId22.ExpandedText = "nsu=http://test.org/UA/Data/ ;i=10853"
            Console.WriteLine(nodeId22)


            ' There is an implicit conversion from a string (representing the expanded text) to a node ID.
            ' You can therefore use the expanded text (string) in place of any node ID object directly.
            Dim nodeId23 = "nsu=http://test.org/UA/Data/ ;i=10853"
            Console.WriteLine(nodeId23)


            ' There is a copy constructor as well, creating a clone of an existing node ID.
            Dim nodeId24a = New UANodeId("nsu=http://test.org/UA/Data/ ;i=10853")
            Console.WriteLine(nodeId24a)
            Dim nodeId24b = New UANodeId(nodeId24a)
            Console.WriteLine(nodeId24b)


            ' We have provided static classes with properties that correspond to all standard nodes specified by 
            ' OPC UA. You can simply refer to these node IDs in your code.
            ' The class names are UADataTypeIds, UAMethodIds, UAObjectIds, UAObjectTypeIds, UAReferenceTypeIds, 
            ' UAVariableIds and UAVariableTypeIds.
            Dim nodeId25 = UAObjectIds.TypesFolder
            Console.WriteLine(nodeId25)


            ' You can also refer to any standard node using its name (in a string form).
            ' Note that assigning a non-existing standard name is not allowed, and throws ArgumentException.
            Dim nodeId26 = New UANodeId()
            nodeId26.StandardName = "TypesFolder"
            Console.WriteLine(nodeId26)


            ' When you browse for nodes in the OPC UA server, every returned node element contains a node ID that
            ' you can use further.
            Dim client27 = New EasyUAClient()
            Dim nodeElementCollection27 = client27.Browse(
                "opc.tcp://opcua.demo-this.com:51210/UA/SampleServer",
                UAObjectIds.Server,
                New UABrowseParameters(UANodeClass.All, {UAReferenceTypeIds.References}))
            Dim nodeId27 = nodeElementCollection27(0).NodeId
            Console.WriteLine(nodeId27)


            ' As above, but using a constructor that takes a node element as an input.
            Dim client28 = New EasyUAClient()
            Dim nodeElementCollection28 = client28.Browse(
                "opc.tcp://opcua.demo-this.com:51210/UA/SampleServer",
                UAObjectIds.Server,
                New UABrowseParameters(UANodeClass.All, {UAReferenceTypeIds.References}))
            Dim nodeId28 = New UANodeId(nodeElementCollection28(0))
            Console.WriteLine(nodeId28)


            ' Or, there is an explicit conversion from a node element as well.
            Dim client29 = New EasyUAClient()
            Dim nodeElementCollection29 = client29.Browse(
                "opc.tcp://opcua.demo-this.com:51210/UA/SampleServer",
                UAObjectIds.Server,
                New UABrowseParameters(UANodeClass.All, {UAReferenceTypeIds.References}))
            Dim nodeId29 = CType(nodeElementCollection29(0), UANodeId)
            Console.WriteLine(nodeId29)
        End Sub
    End Class
End Namespace

COM

// This example shows different ways of constructing OPC UA node IDs.
//
// Find all latest examples here : https://opclabs.doc-that.com/files/onlinedocs/OPCLabs-OpcStudio/Latest/examples.html .

class procedure _Construction.Main;
var
  BrowseParameters: _UABrowseParameters;
  Client27: _EasyUAClient;
  EndpointDescriptor: _UAEndpointDescriptor;
  NodeId1, NodeId2, NodeId3, NodeId4, NodeId5, NodeId6, NodeId7, NodeId8, NodeId9, NodeId10,
  NodeId11, NodeId12, NodeId14, NodeId15, NodeId17, NodeId18,
  NodeId20, NodeId21, NodeId26, NodeId27,
  ServerNodeId, ReferencesNodeId: OpcLabs_EasyOpcUA_TLB._UANodeId;
  NodeId11Result: OleVariant;
  NodeIdParser10, NodeIdParser11, NodeIdParser12: _UANodeIdParser;
  NodeElements27: _UANodeElementCollection;
  OpaqueIdentifier21: Variant;
  ServerNodeDescriptor: _UANodeDescriptor;
  StringParsingError: _StringParsingError;
begin
  // A node ID specifies a namespace (either by an URI or by an index), and an identifier.
  // The identifier can be numeric (an integer), string, GUID, or opaque.

  // A node ID can be specified in string form (so-called expanded text).
  // The code below specifies a namespace URI (nsu=...), and an integer identifier (i=...).
  // Assigning an expanded text to a node ID parses the value being assigned and sets all corresponding
  // properties accordingly.
  NodeId1 := CoUANodeId.Create;
  NodeId1.ExpandedText := 'nsu=http://test.org/UA/Data/ ;i=10853';
  WriteLn(NodeId1.ToString);


  // Similarly, with a string identifier (s=...).
  NodeId2 := CoUANodeId.Create;
  NodeId2.ExpandedText := 'nsu=http://test.org/UA/Data/ ;s=someIdentifier';
  WriteLn(NodeId2.ToString);


  // Actually, "s=" can be omitted (not recommended, though)
  NodeId3 := CoUANodeId.Create;
  NodeId3.ExpandedText := 'nsu=http://test.org/UA/Data/ ;someIdentifier';
  WriteLn(NodeId3.ToString);
  // Notice that the output is normalized - the "s=" is added again.


  // Similarly, with a GUID identifier (g=...)
  NodeId4 := CoUANodeId.Create;
  NodeId4.ExpandedText := 'nsu=http://test.org/UA/Data/ ;g=BAEAF004-1E43-4A06-9EF0-E52010D5CD10';
  WriteLn(NodeId4.ToString);
  // Notice that the output is normalized - uppercase letters in the GUI are converted to lowercase, etc.


  // Similarly, with an opaque identifier (b=..., in Base64 encoding).
  NodeId5 := CoUANodeId.Create;
  NodeId5.ExpandedText := 'nsu=http://test.org/UA/Data/ ;b=AP8=';
  WriteLn(NodeId5.ToString);


  // Namespace index can be used instead of namespace URI. The server is allowed to change the namespace
  // indices between sessions (except for namespace 0), and for this reason, you should avoid the use of
  // namespace indices, and rather use the namespace URIs whenever possible.
  NodeId6 := CoUANodeId.Create;
  NodeId6.ExpandedText := 'ns=2;i=10853';
  WriteLn(NodeId6.ToString);


  // Namespace index can be also specified together with namespace URI. This is still safe, but may be
  // a bit quicker to perform, because the client can just verify the namespace URI instead of looking
  // it up.
  NodeId7 := CoUANodeId.Create;
  NodeId7.ExpandedText := 'nsu=http://test.org/UA/Data/ ;ns=2;i=10853';
  WriteLn(NodeId7.ToString);


  // When neither namespace URI nor namespace index are given, the node ID is assumed to be in namespace
  // with index 0 and URI "http://opcfoundation.org/UA/", which is reserved by OPC UA standard. There are
  // many standard nodes that live in this reserved namespace, but no nodes specific to your servers will
  // be in the reserved namespace, and hence the need to specify the namespace with server-specific nodes.
  NodeId8 := CoUANodeId.Create;
  NodeId8.ExpandedText := 'i=2254';
  WriteLn(NodeId8.ToString);


  // If you attempt to pass in a string that does not conform to the syntax rules,
  // a UANodeIdFormatException is thrown.
  NodeId9 := CoUANodeId.Create;
  try
    NodeId9.ExpandedText := 'nsu=http://test.org/UA/Data/ ;i=notAnInteger';
    WriteLn(NodeId9.ToString);
  except
    on E: EOleException do
    begin
      WriteLn(Format('*** Failure: %s', [E.BaseException.Message]));
    end;
  end;


  // There is a parser object that can be used to parse the expanded texts of node IDs.
  NodeIdParser10 := CoUANodeIdParser.Create;
  NodeId10 := NodeIdParser10.Parse('nsu=http://test.org/UA/Data/ ;i=10853', False);
  WriteLn(NodeId10.ToString);


  // The parser can be used if you want to parse the expanded text of the node ID but do not want
  // exceptions be thrown.
  NodeIdParser11 := CoUANodeIdParser.Create;
  StringParsingError := NodeIdParser11.TryParse('nsu=http://test.org/UA/Data/ ;i=notAnInteger', False, NodeId11Result);
  if StringParsingError = nil then
    begin
      NodeId11 := IUnknown(NodeId11Result) as OpcLabs_EasyOpcUA_TLB._UANodeId;
      WriteLn(NodeId11.ToString);
    end
  else
    WriteLn(Format('*** Failure: %s', [StringParsingError.Message]));


  // You can also use the parser if you have node IDs where you want the default namespace be different
  // from the standard "http://opcfoundation.org/UA/".
  NodeIdParser12 := CoUANodeIdParser.Create;
  NodeIdParser12.DefaultNamespaceUriString := 'http://test.org/UA/Data/';
  NodeId12 := NodeIdParser12.Parse('i=10853', False);
  WriteLn(NodeId12.ToString);


  // You can create a "null" node ID. Such node ID does not actually identify any valid node in OPC UA, but
  // is useful as a placeholder or as a starting point for further modifications of its properties.
  NodeId14 := CoUANodeId.Create;
  WriteLn(NodeId14.ToString);


  // Properties of a node ID can be modified individually. The advantage of this approach is that you do
  // not have to care about syntax of the node ID expanded text.
  NodeId15 := CoUANodeId.Create;
  NodeId15.NamespaceUriString := 'http://test.org/UA/Data/';
  NodeId15.Identifier := 10853;
  WriteLn(NodeId15.ToString);


  // If you know the type of the identifier upfront, it is safer to use typed properties that correspond
  // to specific types of identifier. Here, with an integer identifier.
  NodeId17 := CoUANodeId.Create;
  NodeId17.NamespaceUriString := 'http://test.org/UA/Data/';
  NodeId17.NumericIdentifier := 10853;
  WriteLn(NodeId17.ToString);


  // Similarly, with a string identifier.
  NodeId18 := CoUANodeId.Create;
  NodeId18.NamespaceUriString := 'http://test.org/UA/Data/';
  NodeId18.StringIdentifier := 'someIdentifier';
  WriteLn(NodeId18.ToString);


  // If you have GUID in its string form, the node ID object can parse it for you.
  NodeId20 := CoUANodeId.Create;
  NodeId20.NamespaceUriString := 'http://test.org/UA/Data/';
  NodeId20.GuidIdentifierString := 'BAEAF004-1E43-4A06-9EF0-E52010D5CD10';
  WriteLn(NodeId20.ToString);


  // And, with an opaque identifier.
  NodeId21 := CoUANodeId.Create;
  NodeId21.NamespaceUriString := 'http://test.org/UA/Data/';
//  OpaqueIdentifier21 := VarArrayCreate ([0, 1], varByte);
  OpaqueIdentifier21 := VarArrayCreate ([0, 1], varVariant);
  OpaqueIdentifier21[0] := $00;
  OpaqueIdentifier21[1] := $FF;
  NodeId21.OpaqueIdentifier := PSafeArray (TVarData (OpaqueIdentifier21).VArray);
  WriteLn(NodeId21.ToString);


  // We have built-in a list of all standard nodes specified by OPC UA. You can simply refer to these node IDs in your code.
  // You can refer to any standard node using its name (in a string form).
  // Note that assigning a non-existing standard name is not allowed, and throws ArgumentException.
  NodeId26 := CoUANodeId.Create;
  NodeId26.StandardName := 'TypesFolder';
  WriteLn(NodeId26.ToString);
  // When the UANodeId equals to one of the standard nodes, it is output in the shortened form - as the standard name only.


  // When you browse for nodes in the OPC UA server, every returned node element contains a node ID that
  // you can use further.
  Client27 := CoEasyUAClient.Create;
  EndpointDescriptor := CoUAEndpointDescriptor.Create;
  EndpointDescriptor.UrlString := 'http://opcua.demo-this.com:51211/UA/SampleServer';
  // Browse from the Server node.
  ServerNodeId := CoUANodeId.Create;
  ServerNodeId.StandardName := 'Server';
  ServerNodeDescriptor := CoUANodeDescriptor.Create;
  ServerNodeDescriptor.NodeId := ServerNodeId;
  // Browse all References.
  ReferencesNodeId := CoUANodeId.Create;
  ReferencesNodeId.StandardName := 'References';

  BrowseParameters := CoUABrowseParameters.Create;
  BrowseParameters.NodeClasses := UANodeClass_All;  // this is the default, anyway
  BrowseParameters.ReferenceTypeIds.Add(ReferencesNodeId);

  try
    NodeElements27 := Client27.Browse(EndpointDescriptor, ServerNodeDescriptor, BrowseParameters);
    if NodeElements27.Count <> 0 then
    begin
      NodeId27 := NodeElements27[0].NodeId;
      WriteLn(NodeId27.ToString);
    end;
  except
    on E: EOleException do
    begin
      WriteLn(Format('*** Failure: %s', [E.BaseException.Message]));
    end;
  end;
end;
// This example shows different ways of constructing OPC UA node IDs.
//
// A node ID specifies a namespace (either by an URI or by an index), and an identifier.
// The identifier can be numeric (an integer), string, GUID, or opaque.
//
// Find all latest examples here : https://opclabs.doc-that.com/files/onlinedocs/OPCLabs-OpcStudio/Latest/examples.html .

const UANodeClass_All = 255;


// A node ID can be specified in string form (so-called expanded text).
// The code below specifies a namespace URI (nsu=...), and an integer identifier (i=...).
// Assigning an expanded text to a node ID parses the value being assigned and sets all corresponding
// properties accordingly.
$NodeId1 = new COM("OpcLabs.EasyOpc.UA.AddressSpace.UANodeId");
$NodeId1->ExpandedText = "nsu=http://test.org/UA/Data/ ;i=10853";
printf("%s\n", $NodeId1);


// Similarly, with a string identifier (s=...).
$NodeId2 = new COM("OpcLabs.EasyOpc.UA.AddressSpace.UANodeId");
$NodeId2->ExpandedText = "nsu=http://test.org/UA/Data/ ;s=someIdentifier";
printf("%s\n", $NodeId2);


// Actually, "s=" can be omitted (not recommended, though)
$NodeId3 = new COM("OpcLabs.EasyOpc.UA.AddressSpace.UANodeId");
$NodeId3->ExpandedText = "nsu=http://test.org/UA/Data/ ;someIdentifier";
printf("%s\n", $NodeId3);
// Notice that the output is normalized - the "s=" is added again.


// Similarly, with a GUID identifier (g=...)
$NodeId4 = new COM("OpcLabs.EasyOpc.UA.AddressSpace.UANodeId");
$NodeId4->ExpandedText = "nsu=http://test.org/UA/Data/ ;g=BAEAF004-1E43-4A06-9EF0-E52010D5CD10";
printf("%s\n", $NodeId4);
// Notice that the output is normalized - uppercase letters in the GUI are converted to lowercase, etc.


// Similarly, with an opaque identifier (b=..., in Base64 encoding).
$NodeId5 = new COM("OpcLabs.EasyOpc.UA.AddressSpace.UANodeId");
$NodeId5->ExpandedText = "nsu=http://test.org/UA/Data/ ;b=AP8=";
printf("%s\n", $NodeId5);


// Namespace index can be used instead of namespace URI. The server is allowed to change the namespace
// indices between sessions (except for namespace 0), and for this reason, you should avoid the use of
// namespace indices, and rather use the namespace URIs whenever possible.
$NodeId6 = new COM("OpcLabs.EasyOpc.UA.AddressSpace.UANodeId");
$NodeId6->ExpandedText = "ns=2;i=10853";
printf("%s\n", $NodeId6);


// Namespace index can be also specified together with namespace URI. This is still safe, but may be
// a bit quicker to perform, because the client can just verify the namespace URI instead of looking
// it up.
$NodeId7 = new COM("OpcLabs.EasyOpc.UA.AddressSpace.UANodeId");
$NodeId7->ExpandedText = "nsu=http://test.org/UA/Data/ ;ns=2;i=10853";
printf("%s\n", $NodeId7);


// When neither namespace URI nor namespace index are given, the node ID is assumed to be in namespace
// with index 0 and URI "http://opcfoundation.org/UA/", which is reserved by OPC UA standard. There are
// many standard nodes that live in this reserved namespace, but no nodes specific to your servers will
// be in the reserved namespace, and hence the need to specify the namespace with server-specific nodes.
$NodeId8 = new COM("OpcLabs.EasyOpc.UA.AddressSpace.UANodeId");
$NodeId8->ExpandedText = "i=2254";
printf("%s\n", $NodeId8);


// If you attempt to pass in a string that does not conform to the syntax rules,
// a UANodeIdFormatException is thrown.
$NodeId9 = new COM("OpcLabs.EasyOpc.UA.AddressSpace.UANodeId");
try
{
    $NodeId9->ExpandedText = "nsu=http://test.org/UA/Data/ ;i=notAnInteger";
    printf("%s\n", $NodeId9);
}
catch (com_exception $e)
{
    printf("*** Failure: %s\n", $e->getMessage());
}


// There is a parser object that can be used to parse the expanded texts of node IDs.
$NodeIdParser10 = new COM("OpcLabs.EasyOpc.UA.AddressSpace.Parsing.UANodeIdParser");
$NodeId10 = $NodeIdParser10->Parse("nsu=http://test.org/UA/Data/ ;i=10853", False);
printf("%s\n", $NodeId10);


// The parser can be used if you want to parse the expanded text of the node ID but do not want
// exceptions be thrown.
$NodeId11 = new COM("OpcLabs.EasyOpc.UA.AddressSpace.UANodeId");
$NodeIdParser11 = new COM("OpcLabs.EasyOpc.UA.AddressSpace.Parsing.UANodeIdParser");
$StringParsingError = $NodeIdParser11->TryParse("nsu=http://test.org/UA/Data/ ;i=notAnInteger", False, $NodeId11);
if (is_null($StringParsingError))
    printf("%s\n", $NodeId11);
else    
    printf("*** Failure: %s\n", $StringParsingError->Message);


// You can also use the parser if you have node IDs where you want the default namespace be different
// from the standard "http://opcfoundation.org/UA/".
$NodeIdParser12 = new COM("OpcLabs.EasyOpc.UA.AddressSpace.Parsing.UANodeIdParser");
$NodeIdParser12->DefaultNamespaceUriString = "http://test.org/UA/Data/";
$NodeId12 = $NodeIdParser12->Parse("i=10853", False);
printf("%s\n", $NodeId12);


// You can create a "null" node ID. Such node ID does not actually identify any valid node in OPC UA, but
// is useful as a placeholder or as a starting point for further modifications of its properties.
$NodeId14 = new COM("OpcLabs.EasyOpc.UA.AddressSpace.UANodeId");
printf("%s\n", $NodeId14);


// Properties of a node ID can be modified individually. The advantage of this approach is that you do
// not have to care about syntax of the node ID expanded text.
$NodeId15 = new COM("OpcLabs.EasyOpc.UA.AddressSpace.UANodeId");
$NodeId15->NamespaceUriString = "http://test.org/UA/Data/";
$NodeId15->Identifier = 10853;
printf("%s\n", $NodeId15);


// If you know the type of the identifier upfront, it is safer to use typed properties that correspond
// to specific types of identifier. Here, with an integer identifier.
$NodeId17 = new COM("OpcLabs.EasyOpc.UA.AddressSpace.UANodeId");
$NodeId17->NamespaceUriString = "http://test.org/UA/Data/";
$NodeId17->NumericIdentifier = 10853;
printf("%s\n", $NodeId17);


// Similarly, with a string identifier.
$NodeId18 = new COM("OpcLabs.EasyOpc.UA.AddressSpace.UANodeId");
$NodeId18->NamespaceUriString = "http://test.org/UA/Data/";
$NodeId18->StringIdentifier = "someIdentifier";
printf("%s\n", $NodeId18);


// If you have GUID in its string form, the node ID object can parse it for you.
$NodeId20 = new COM("OpcLabs.EasyOpc.UA.AddressSpace.UANodeId");
$NodeId20->NamespaceUriString = "http://test.org/UA/Data/";
$NodeId20->GuidIdentifierString = "BAEAF004-1E43-4A06-9EF0-E52010D5CD10";
printf("%s\n", $NodeId20);


// And, with an opaque identifier.
$NodeId21 = new COM("OpcLabs.EasyOpc.UA.AddressSpace.UANodeId");
$NodeId21->NamespaceUriString = "http://test.org/UA/Data/";
$OpaqueIdentifier21[0] = 0x00;
$OpaqueIdentifier21[1] = 0xFF;
$NodeId21->OpaqueIdentifier = $OpaqueIdentifier21;
printf("%s\n", $NodeId21);


// We have built-in a list of all standard nodes specified by OPC UA. You can simply refer to these node IDs in your code.
// You can refer to any standard node using its name (in a string form).
// Note that assigning a non-existing standard name is not allowed, and throws ArgumentException.
$NodeId26 = new COM("OpcLabs.EasyOpc.UA.AddressSpace.UANodeId");
$NodeId26->StandardName = "TypesFolder";
printf("%s\n", $NodeId26);
// When the UANodeId equals to one of the standard nodes, it is output in the shortened form - as the standard name only.


// When you browse for nodes in the OPC UA server, every returned node element contains a node ID that
// you can use further.
$Client27 = new COM("OpcLabs.EasyOpc.UA.EasyUAClient");
$EndpointDescriptor = new COM("OpcLabs.EasyOpc.UA.UAEndpointDescriptor");
$EndpointDescriptor->UrlString = "http://opcua.demo-this.com:51211/UA/SampleServer";
// Browse from the Server node.
$ServerNodeId = new COM("OpcLabs.EasyOpc.UA.AddressSpace.UANodeId");
$ServerNodeId->StandardName = "Server";
$ServerNodeDescriptor = new COM("OpcLabs.EasyOpc.UA.UANodeDescriptor");
$ServerNodeDescriptor->NodeId = $ServerNodeId;
// Browse all References.
$ReferencesNodeId = new COM("OpcLabs.EasyOpc.UA.AddressSpace.UANodeId");
$ReferencesNodeId->StandardName = "References";

$BrowseParameters = new COM("OpcLabs.EasyOpc.UA.UABrowseParameters");
$BrowseParameters->NodeClasses = UANodeClass_All;  // this is the default, anyway
$BrowseParameters->ReferenceTypeIds->Add($ReferencesNodeId);

try
{
    $NodeElements27 = $Client27->Browse($EndpointDescriptor, $ServerNodeDescriptor, $BrowseParameters);
    if ($NodeElements27->Count != 0) {
        $NodeId27 = $NodeElements27[0]->NodeId;
        printf("%s\n", $NodeId27);
    }
}
catch (com_exception $e)
{
    printf("*** Failure: %s\n", $e->getMessage());
    exit();
}
REM This example shows different ways of constructing OPC UA node IDs.
REM
REM Find all latest examples here : https://opclabs.doc-that.com/files/onlinedocs/OPCLabs-OpcStudio/Latest/examples.html .

Private Sub Construction_Main_Command_Click()
    OutputText = ""
    
    ' A node ID specifies a namespace (either by an URI or by an index), and an identifier.
    ' The identifier can be numeric (an integer), string, GUID, or opaque.

    ' A node ID can be specified in string form (so-called expanded text).
    ' The code below specifies a namespace URI (nsu=...), and an integer identifier (i=...).
    ' Assigning an expanded text to a node ID parses the value being assigned and sets all corresponding
    ' properties accordingly.
    Dim nodeId1 As New UANodeId
    nodeId1.expandedText = "nsu=http://test.org/UA/Data/ ;i=10853"
    OutputText = OutputText & nodeId1 & vbCrLf


    ' Similarly, with a string identifier (s=...).
    Dim nodeId2 As New UANodeId
    nodeId2.expandedText = "nsu=http://test.org/UA/Data/ ;s=someIdentifier"
    OutputText = OutputText & nodeId2 & vbCrLf
    
    
    ' Actually, "s=" can be omitted (not recommended, though)
    Dim nodeId3 As New UANodeId
    nodeId3.expandedText = "nsu=http://test.org/UA/Data/ ;someIdentifier"
    OutputText = OutputText & nodeId3 & vbCrLf
    ' Notice that the output is normalized - the "s=" is added again.
     
    ' Similarly, with a GUID identifier (g=...)
    Dim nodeId4 As New UANodeId
    nodeId4.expandedText = "nsu=http://test.org/UA/Data/ ;g=BAEAF004-1E43-4A06-9EF0-E52010D5CD10"
    OutputText = OutputText & nodeId4 & vbCrLf
    ' Notice that the output is normalized - uppercase letters in the GUI are converted to lowercase, etc.
    
    
    ' Similarly, with an opaque identifier (b=..., in Base64 encoding).
    Dim nodeId5 As New UANodeId
    nodeId5.expandedText = "nsu=http://test.org/UA/Data/ ;b=AP8="
    OutputText = OutputText & nodeId5 & vbCrLf
       
       
    ' Namespace index can be used instead of namespace URI. The server is allowed to change the namespace
    ' indices between sessions (except for namespace 0), and for this reason, you should avoid the use of
    ' namespace indices, and rather use the namespace URIs whenever possible.
    Dim nodeId6 As New UANodeId
    nodeId6.expandedText = "ns=2;i=10853"
    OutputText = OutputText & nodeId6 & vbCrLf
       
       
    ' Namespace index can be also specified together with namespace URI. This is still safe, but may be
    ' a bit quicker to perform, because the client can just verify the namespace URI instead of looking
    ' it up.
    Dim nodeId7 As New UANodeId
    nodeId7.expandedText = "nsu=http://test.org/UA/Data/ ;ns=2;i=10853"
    OutputText = OutputText & nodeId7 & vbCrLf
       
       
    ' When neither namespace URI nor namespace index are given, the node ID is assumed to be in namespace
    ' with index 0 and URI "http://opcfoundation.org/UA/", which is reserved by OPC UA standard. There are
    ' many standard nodes that live in this reserved namespace, but no nodes specific to your servers will
    ' be in the reserved namespace, and hence the need to specify the namespace with server-specific nodes.
    Dim nodeId8 As New UANodeId
    nodeId8.expandedText = "i=2254"
    OutputText = OutputText & nodeId8 & vbCrLf
       
       
    ' If you attempt to pass in a string that does not conform to the syntax rules,
    ' a UANodeIdFormatException is thrown.
    Dim nodeId9 As New UANodeId
    On Error Resume Next
    nodeId9.expandedText = "nsu=http://test.org/UA/Data/ ;i=notAnInteger"
    OutputText = OutputText & nodeId9 & vbCrLf
    If Err.Number <> 0 Then
        OutputText = OutputText & "*** Failure: " & Err.Source & ": " & Err.Description & vbCrLf
    End If
    On Error GoTo 0


    ' There is a parser object that can be used to parse the expanded texts of node IDs.
    Dim nodeIdParser10 As New UANodeIdParser
    Dim nodeId10 As UANodeId
    Set nodeId10 = nodeIdParser10.Parse("nsu=http://test.org/UA/Data/ ;i=10853", False)
    OutputText = OutputText & nodeId10 & vbCrLf
       
       
    ' The parser can be used if you want to parse the expanded text of the node ID but do not want
    ' exceptions be thrown.
    Dim nodeIdParser11 As New UANodeIdParser
    Dim stringParsingError As stringParsingError
    Dim nodeId11 As UANodeId
    Set stringParsingError = nodeIdParser11.TryParse("nsu=http://test.org/UA/Data/ ;i=notAnInteger", False, nodeId11)
    If stringParsingError Is Nothing Then
        OutputText = OutputText & nodeId11 & vbCrLf
    Else
        OutputText = OutputText & "*** Failure: " & stringParsingError.Message & vbCrLf
    End If
       
       
    ' You can also use the parser if you have node IDs where you want the default namespace be different
    ' from the standard "http://opcfoundation.org/UA/".
    Dim nodeIdParser12 As New UANodeIdParser
    nodeIdParser12.DefaultNamespaceUriString = "http://test.org/UA/Data/"
    Dim nodeId12 As UANodeId
    Set nodeId12 = nodeIdParser12.Parse("i=10853", False)
    OutputText = OutputText & nodeId12 & vbCrLf
       
       
    ' You can create a "null" node ID. Such node ID does not actually identify any valid node in OPC UA, but
    ' is useful as a placeholder or as a starting point for further modifications of its properties.
    Dim nodeId14 As New UANodeId
    OutputText = OutputText & nodeId14 & vbCrLf
       
       
    ' If you know the type of the identifier upfront, it is safer to use typed properties that correspond
    ' to specific types of identifier. Here, with an integer identifier.
    Dim nodeId17 As New UANodeId
    nodeId17.NamespaceUriString = "http://test.org/UA/Data/"
    nodeId17.NumericIdentifier = 10853
    OutputText = OutputText & nodeId17 & vbCrLf
       
       
    ' Similarly, with a string identifier.
    Dim nodeId18 As New UANodeId
    nodeId18.NamespaceUriString = "http://test.org/UA/Data/"
    nodeId18.StringIdentifier = "someIdentifier"
    OutputText = OutputText & nodeId18 & vbCrLf
       
       
    ' If you have GUID in its string form, the node ID object can parse it for you.
    Dim nodeId20 As New UANodeId
    nodeId20.NamespaceUriString = "http://test.org/UA/Data/"
    nodeId20.GuidIdentifierString = "BAEAF004-1E43-4A06-9EF0-E52010D5CD10"
    OutputText = OutputText & nodeId20 & vbCrLf
       
       
    ' And, with an opaque identifier.
    Dim nodeId21 As New UANodeId
    nodeId21.NamespaceUriString = "http://test.org/UA/Data/"
    Dim opaqueIdentifier21(1) As Byte
    opaqueIdentifier21(0) = &H0&
    opaqueIdentifier21(1) = &HFF&
    nodeId21.SetOpaqueIdentifier opaqueIdentifier21
    OutputText = OutputText & nodeId21 & vbCrLf


    ' We have built-in a list of all standard nodes specified by OPC UA. You can simply refer to these node IDs in your code.
    ' You can refer to any standard node using its name (in a string form).
    ' Note that assigning a non-existing standard name is not allowed, and throws ArgumentException.
    Dim nodeId26 As New UANodeId
    nodeId26.StandardName = "TypesFolder"
    OutputText = OutputText & nodeId26 & vbCrLf
    ' When the UANodeId equals to one of the standard nodes, it is output in the shortened form - as the standard name only.
    
      
    ' When you browse for nodes in the OPC UA server, every returned node element contains a node ID that
    ' you can use further.
    Dim client27 As New EasyUAClient
    Dim endpointDescriptor As New UAEndpointDescriptor
    endpointDescriptor.UrlString = "opc.tcp://opcua.demo-this.com:51210/UA/SampleServer"
    ' Browse from the Server node.
    Dim serverNodeId As New UANodeId
    serverNodeId.StandardName = "Server"
    Dim serverNodedescriptor As New UANodeDescriptor
    Set serverNodedescriptor.NodeId = serverNodeId
    ' Browse all References.
    Dim referencesNodeId As New UANodeId
    referencesNodeId.StandardName = "References"
    
    Dim browseParameters As New UABrowseParameters
    browseParameters.NodeClasses = UANodeClass_All ' this is the default, anyway
    browseParameters.ReferenceTypeIds.Add referencesNodeId
    
    On Error Resume Next
    Dim nodeElements27 As UANodeElementCollection
    Set nodeElements27 = client27.Browse(endpointDescriptor, serverNodedescriptor, browseParameters)
    If Err.Number <> 0 Then
        OutputText = OutputText & "*** Failure: " & Err.Source & ": " & Err.Description & vbCrLf
        Exit Sub
    End If
    On Error GoTo 0

    If nodeElements27.Count <> 0 Then
        Dim nodeId27 As UANodeId
        Set nodeId27 = nodeElements27(0).NodeId
        OutputText = OutputText & nodeId27 & vbCrLf
    End If
   
End Sub
Rem This example shows different ways of constructing OPC UA node IDs.
Rem
Rem Find all latest examples here : https://opclabs.doc-that.com/files/onlinedocs/OPCLabs-OpcStudio/Latest/examples.html .

Option Explicit

' A node ID specifies a namespace (either by an URI or by an index), and an identifier.
' The identifier can be numeric (an integer), string, GUID, or opaque.

Const UANodeClass_All = 255


' A node ID can be specified in string form (so-called expanded text). 
' The code below specifies a namespace URI (nsu=...), and an integer identifier (i=...).
' Assigning an expanded text to a node ID parses the value being assigned and sets all corresponding
' properties accordingly.
Dim NodeId1: Set NodeId1 = CreateObject("OpcLabs.EasyOpc.UA.AddressSpace.UANodeId")
NodeId1.ExpandedText = "nsu=http://test.org/UA/Data/ ;i=10853"
WScript.Echo NodeId1


' Similarly, with a string identifier (s=...).
Dim NodeId2: Set NodeId2 = CreateObject("OpcLabs.EasyOpc.UA.AddressSpace.UANodeId")
NodeId2.ExpandedText = "nsu=http://test.org/UA/Data/ ;s=someIdentifier"
WScript.Echo NodeId2


' Actually, "s=" can be omitted (not recommended, though)
Dim NodeId3: Set NodeId3 = CreateObject("OpcLabs.EasyOpc.UA.AddressSpace.UANodeId")
NodeId3.ExpandedText = "nsu=http://test.org/UA/Data/ ;someIdentifier"
WScript.Echo NodeId3
' Notice that the output is normalized - the "s=" is added again.


' Similarly, with a GUID identifier (g=...)
Dim NodeId4: Set NodeId4 = CreateObject("OpcLabs.EasyOpc.UA.AddressSpace.UANodeId")
NodeId4.ExpandedText = "nsu=http://test.org/UA/Data/ ;g=BAEAF004-1E43-4A06-9EF0-E52010D5CD10"
WScript.Echo NodeId4
' Notice that the output is normalized - uppercase letters in the GUI are converted to lowercase, etc.


' Similarly, with an opaque identifier (b=..., in Base64 encoding).
Dim NodeId5: Set NodeId5 = CreateObject("OpcLabs.EasyOpc.UA.AddressSpace.UANodeId")
NodeId5.ExpandedText = "nsu=http://test.org/UA/Data/ ;b=AP8="
WScript.Echo NodeId5


' Namespace index can be used instead of namespace URI. The server is allowed to change the namespace 
' indices between sessions (except for namespace 0), and for this reason, you should avoid the use of
' namespace indices, and rather use the namespace URIs whenever possible.
Dim NodeId6: Set NodeId6 = CreateObject("OpcLabs.EasyOpc.UA.AddressSpace.UANodeId")
NodeId6.ExpandedText = "ns=2;i=10853"
WScript.Echo NodeId6


' Namespace index can be also specified together with namespace URI. This is still safe, but may be 
' a bit quicker to perform, because the client can just verify the namespace URI instead of looking 
' it up.
Dim NodeId7: Set NodeId7 = CreateObject("OpcLabs.EasyOpc.UA.AddressSpace.UANodeId")
NodeId7.ExpandedText = "nsu=http://test.org/UA/Data/ ;ns=2;i=10853"
WScript.Echo NodeId7


' When neither namespace URI nor namespace index are given, the node ID is assumed to be in namespace
' with index 0 and URI "http://opcfoundation.org/UA/", which is reserved by OPC UA standard. There are 
' many standard nodes that live in this reserved namespace, but no nodes specific to your servers will 
' be in the reserved namespace, and hence the need to specify the namespace with server-specific nodes.
Dim NodeId8: Set NodeId8 = CreateObject("OpcLabs.EasyOpc.UA.AddressSpace.UANodeId")
NodeId8.ExpandedText = "i=2254"
WScript.Echo NodeId8


' If you attempt to pass in a string that does not conform to the syntax rules, 
' a UANodeIdFormatException is thrown.
Dim NodeId9: Set NodeId9 = CreateObject("OpcLabs.EasyOpc.UA.AddressSpace.UANodeId")
On Error Resume Next
NodeId9.ExpandedText = "nsu=http://test.org/UA/Data/ ;i=notAnInteger"
If Err.Number = 0 Then
    WScript.Echo NodeId9
Else
    WScript.Echo "*** Failure: " & Err.Source & ": " & Err.Description
End If
On Error Goto 0


' There is a parser object that can be used to parse the expanded texts of node IDs. 
Dim NodeIdParser10: Set NodeIdParser10 = CreateObject("OpcLabs.EasyOpc.UA.AddressSpace.Parsing.UANodeIdParser")
Dim NodeId10: Set NodeId10 = NodeIdParser10.Parse("nsu=http://test.org/UA/Data/ ;i=10853", False)
WScript.Echo NodeId10


' The parser can be used if you want to parse the expanded text of the node ID but do not want 
' exceptions be thrown.
Dim NodeIdParser11: Set NodeIdParser11 = CreateObject("OpcLabs.EasyOpc.UA.AddressSpace.Parsing.UANodeIdParser")
Dim NodeId11
Dim StringParsingError: Set StringParsingError = NodeIdParser11.TryParse("nsu=http://test.org/UA/Data/ ;i=notAnInteger", False, NodeId11)
If StringParsingError Is Nothing Then
    WScript.Echo NodeId11
Else
    WScript.Echo "*** Failure: " & StringParsingError.Message
End If


' You can also use the parser if you have node IDs where you want the default namespace be different 
' from the standard "http://opcfoundation.org/UA/".
Dim NodeIdParser12: Set NodeIdParser12 = CreateObject("OpcLabs.EasyOpc.UA.AddressSpace.Parsing.UANodeIdParser")
NodeIdParser12.DefaultNamespaceUriString = "http://test.org/UA/Data/"
Dim NodeId12: Set NodeId12 = NodeIdParser12.Parse("i=10853", False)
WScript.Echo NodeId12


' You can create a "null" node ID. Such node ID does not actually identify any valid node in OPC UA, but 
' is useful as a placeholder or as a starting point for further modifications of its properties.
Dim NodeId14: Set NodeId14 = CreateObject("OpcLabs.EasyOpc.UA.AddressSpace.UANodeId")
WScript.Echo NodeId14


' Properties of a node ID can be modified individually. The advantage of this approach is that you do 
' not have to care about syntax of the node ID expanded text.
Dim NodeId15: Set NodeId15 = CreateObject("OpcLabs.EasyOpc.UA.AddressSpace.UANodeId")
NodeId15.NamespaceUriString = "http://test.org/UA/Data/"
NodeId15.Identifier = 10853
WScript.Echo NodeId15


' If you know the type of the identifier upfront, it is safer to use typed properties that correspond 
' to specific types of identifier. Here, with an integer identifier.
Dim NodeId17: Set NodeId17 = CreateObject("OpcLabs.EasyOpc.UA.AddressSpace.UANodeId")
NodeId17.NamespaceUriString = "http://test.org/UA/Data/"
NodeId17.NumericIdentifier = 10853
WScript.Echo NodeId17


' Similarly, with a string identifier.
Dim NodeId18: Set NodeId18 = CreateObject("OpcLabs.EasyOpc.UA.AddressSpace.UANodeId")
NodeId18.NamespaceUriString = "http://test.org/UA/Data/"
NodeId18.StringIdentifier = "someIdentifier"
WScript.Echo NodeId18


' If you have GUID in its string form, the node ID object can parse it for you.
Dim NodeId20: Set NodeId20 = CreateObject("OpcLabs.EasyOpc.UA.AddressSpace.UANodeId")
NodeId20.NamespaceUriString = "http://test.org/UA/Data/"
NodeId20.GuidIdentifierString = "BAEAF004-1E43-4A06-9EF0-E52010D5CD10"
WScript.Echo NodeId20


' And, with an opaque identifier.
Dim NodeId21: Set NodeId21 = CreateObject("OpcLabs.EasyOpc.UA.AddressSpace.UANodeId")
NodeId21.NamespaceUriString = "http://test.org/UA/Data/"
NodeId21.OpaqueIdentifier = Array(&H00, &HFF)
WScript.Echo NodeId21


' We have built-in a list of all standard nodes specified by OPC UA. You can simply refer to these node IDs in your code.
' You can refer to any standard node using its name (in a string form).
' Note that assigning a non-existing standard name is not allowed, and throws ArgumentException.
Dim NodeId26: Set NodeId26 = CreateObject("OpcLabs.EasyOpc.UA.AddressSpace.UANodeId")
NodeId26.StandardName = "TypesFolder"
WScript.Echo NodeId26
' When the UANodeId equals to one of the standard nodes, it is output in the shortened form - as the standard name only.


' When you browse for nodes in the OPC UA server, every returned node element contains a node ID that
' you can use further.
Dim Client27: Set Client27 = CreateObject("OpcLabs.EasyOpc.UA.EasyUAClient")
Dim EndpointDescriptor: Set EndpointDescriptor = CreateObject("OpcLabs.EasyOpc.UA.UAEndpointDescriptor")
EndpointDescriptor.UrlString = "opc.tcp://opcua.demo-this.com:51210/UA/SampleServer"
' Browse from the Server node.
Dim ServerNodeId: Set ServerNodeId = CreateObject("OpcLabs.EasyOpc.UA.AddressSpace.UANodeId")
ServerNodeId.StandardName = "Server"
Dim ServerNodeDescriptor: Set ServerNodeDescriptor = CreateObject("OpcLabs.EasyOpc.UA.UANodeDescriptor")
ServerNodeDescriptor.NodeId = ServerNodeId
' Browse all References.
Dim ReferencesNodeId: Set ReferencesNodeId = CreateObject("OpcLabs.EasyOpc.UA.AddressSpace.UANodeId")
ReferencesNodeId.StandardName = "References"
'
Dim BrowseParameters: Set BrowseParameters = CreateObject("OpcLabs.EasyOpc.UA.UABrowseParameters")
BrowseParameters.NodeClasses = UANodeClass_All  ' this is the default, anyway
BrowseParameters.ReferenceTypeIds.Add ReferencesNodeId
'
On Error Resume Next
Dim NodeElementCollection27: Set NodeElementCollection27 = Client27.Browse( _
    EndpointDescriptor, ServerNodeDescriptor, BrowseParameters)
If Err.Number = 0 Then
    If NodeElementCollection27.Count <> 0 Then
        Dim NodeId27: Set NodeId27 = NodeElementCollection27(0).NodeId
        WScript.Echo NodeId27
    End If
Else
    WScript.Echo "*** Failure: " & Err.Source & ": " & Err.Description
End If
On Error Goto 0

 

See Also

Conceptual